package com.ruoyi.web.cq;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.h1wUtils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.entity.domain.Conver;
import com.ruoyi.entity.domain.Image;
import com.ruoyi.entity.domain.MsgLog;
import com.ruoyi.entity.domain.Recommend;
import com.ruoyi.entity.service.*;
import lombok.SneakyThrows;
import net.lz1998.cq.event.message.CQGroupMessageEvent;
import net.lz1998.cq.event.message.CQPrivateMessageEvent;
import net.lz1998.cq.retdata.MessageData;
import net.lz1998.cq.robot.CQPlugin;
import net.lz1998.cq.robot.CoolQ;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Component
public class CQResolver extends CQPlugin {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private IConverService converService;
    @Autowired
    private IMsgLogService msgLogService;
    @Autowired
    private IImageService imageService;
    @Autowired
    private IOptionService optionService;
    @Autowired
    private IRecommendService recommendService;


    @SneakyThrows
    @Override
    public int onPrivateMessage(CoolQ cq, CQPrivateMessageEvent event) {
        CQMessage message = new CQMessage(event);
        msgLogService.save(message.getMsgLog());
        String req = message.getMessageContent();
        while (head(req, " "))
            req = req.substring(1);
        if (head(req, "#")) {
            req = req.substring(1);
            Long senderId = message.getUserId();
            String senderName = message.getUserName();
            if (head(req,"encode")){

                System.out.println();
            }
            if (head(req,"decode")){

                System.out.println();
            }
        }
        return MESSAGE_IGNORE;
    }

    @Override
    public int onGroupMessage(CoolQ cq, CQGroupMessageEvent event) {
        CQMessage message = new CQMessage(event);
        msgLogService.save(message.getMsgLog());
        String req = message.getMessageContent();

        while (head(req, " "))
            req = req.substring(1);
        if (head(req, "#")) {
            req = req.substring(1);
            Long senderId = message.getUserId();
            String senderName = message.getUserName();
            Long groupId = message.getGroupId();
            if (!inCD("CmdColdDownTime", groupId)) {
                setCD("CmdColdDownTime", groupId);
                Conver conver = converService.getConverByReq(cmd(req));
                if (conver != null) {
                    Map resp = (Map) JSON.parse(conver.getConverResp());
                    if (checkFUNC(conver, groupId, senderId)) {
                        try {
                            Method method = this.getClass().getMethod(resp.get("func").toString(), Class.forName("net.lz1998.cq.robot.CoolQ"), Class.forName("java.lang.Long"), Class.forName("java.lang.Long"));
                            return Integer.valueOf(method.invoke(this, cq, groupId, senderId).toString());
                        } catch (Exception e) {
                        }
                    }
                    if (checkANSWERS(conver, groupId, senderId)) {
                        List<String> strings = (List<String>) resp.get("value");
                        String result = strings.get(new Random().nextInt(strings.size()));
                        sendGroupMsg(cq, groupId, result);
                        return MESSAGE_BLOCK;
                    }
                    if (checkAPI(conver, groupId, senderId)) {
                        String result = getTarget(senderId) + "\n" + WebUtil.GetUrl(resp.get("url").toString());
                        sendGroupMsg(cq, groupId, result);
                        return MESSAGE_BLOCK;
                    }
                    if (checkMAIL(conver, groupId, senderId)) {
                        String result = getTarget(senderId) + "\n" + resp.get("message1").toString();
                        sendGroupMsg(cq, groupId, result);
                        new MailUtil(false).doSendHtmlEmail(resp.get("title").toString(), resp.get("content").toString(), senderId + "@qq.com", new File(getRecommend().getRecommendPath()));
                        result = getTarget(senderId) + "\n" + resp.get("message2").toString();
                        sendGroupMsg(cq, groupId, result);
                        return MESSAGE_BLOCK;
                    }
                    if (checkTEXTS(conver, groupId, senderId)) {
                        List<String> strings = (List<String>) resp.get("value");
                        String result = getTarget(senderId);
                        for (String string : strings)
                            result = result + "\n" + string;
                        sendGroupMsg(cq, groupId, result);
                        return MESSAGE_BLOCK;
                    }
                    if (checkSETU(conver, groupId, senderId)) {
                        if (!inCD("SetuColdDownTime", groupId) || isAdmin(senderId)) {
                            if (!isAdmin(senderId))
                                setCD("SetuColdDownTime", groupId);
                            String keyword = param(req);
                            String load = "";
                            String result = "";
                            Image image = null;
                            if (checkONLINE(conver, groupId, senderId)) {
                                load = "\n" + loadImg(keyword);
                                result = getImgOn(keyword);
                            }
                            if (checkOFFLINE(conver, groupId, senderId)) {
                                result = getImgOff(keyword);
                            }
                            result = getTarget(senderId) + load + "\n" + result;
                            sendGroupMsg(cq, groupId, result, !result.equals("Found 0."));
                            //sendGroupMsg(cq, groupId, result);
                            return MESSAGE_BLOCK;
                        } else {
                            String result = getTarget(senderId) + "\n冷却中 (" + getCD("SetuColdDownTime", groupId) + " 秒)";
                            sendGroupMsg(cq, groupId, result);
                            return MESSAGE_BLOCK;
                        }
                    }
                }
            } else {
                String result = getTarget(senderId) + "\n系统繁忙 (" + getCD("CmdColdDownTime", groupId) + " 秒)";
                sendGroupMsg(cq, groupId, result);
                return MESSAGE_BLOCK;
            }
        }
        return MESSAGE_IGNORE;
    }

    public int forseLoad(CoolQ cq, Long groupId, Long userId) {
        List<Image> list = imageService.getImagesUnLoad();
        String result = getTarget(userId) + "\n检索到 " + list.size() + " 条未缓存数据，启用强制缓存";
        sendGroupMsg(cq, groupId, result);
        Integer count = 0;
        for (Image image : list) {
            try {
                DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicMas());
                image.setPicStatus(1);
                image.setPicPath("/profile" + image.getPicMas().substring(image.getPicMas().lastIndexOf("/")));
                imageService.updateById(image);
                count++;
            } catch (Exception e1) {
                try {
                    DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicUrl());
                    image.setPicStatus(1);
                    image.setPicPath("/profile" + image.getPicUrl().substring(image.getPicUrl().lastIndexOf("/")));
                    imageService.updateById(image);
                    count++;
                } catch (Exception e2) {
                    image.setPicStatus(2);
                    image.setPicPath("");
                    imageService.updateById(image);
                }
            }
        }
        result = getTarget(userId) + "\n强制缓存已完成，成功缓存 " + count + " 条数据";
        sendGroupMsg(cq, groupId, result);
        return MESSAGE_BLOCK;
    }

    public int forseLoadError(CoolQ cq, Long groupId, Long userId) {
        List<Image> list = imageService.getImagesError();
        String result = getTarget(userId) + "\n检索到 " + list.size() + " 条异常数据，重新缓存";
        sendGroupMsg(cq, groupId, result);
        Integer count = 0;
        for (Image image : list) {
            try {
                DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicMas());
                image.setPicStatus(1);
                image.setPicPath("/profile" + image.getPicMas().substring(image.getPicMas().lastIndexOf("/")));
                imageService.updateById(image);
                count++;
            } catch (Exception e1) {
                try {
                    DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicUrl());
                    image.setPicStatus(1);
                    image.setPicPath("/profile" + image.getPicUrl().substring(image.getPicUrl().lastIndexOf("/")));
                    imageService.updateById(image);
                    count++;
                } catch (Exception e2) {
                    image.setPicStatus(2);
                    image.setPicPath("");
                    imageService.updateById(image);
                }
            }
        }
        result = getTarget(userId) + "\n重新缓存已完成，成功缓存 " + count + " 条数据";
        sendGroupMsg(cq, groupId, result);
        return MESSAGE_BLOCK;
    }

    private String loadImg(String keyword) {
        if (keyword != "")
            try {
                keyword = "&keyword=" + WebUtil.encode(keyword);
            } catch (Exception e) {
            }
        String webUrl = "https://api.lolicon.app/setu/?r18=2&num=10&apikey=" + optionService.getOption("ApiKey").getOptionValue() + keyword;
        String webResult = WebUtil.GetUrl(webUrl);
        List<Map> tempList = (List<Map>) ((Map) JSON.parse(webResult)).get("data");
        Integer countAll = tempList.size();
        Integer countLoad = 0;
        Integer countPart = 0;
        for (Map temp : tempList) {
            Image image = new Image();
            image.setPicId(new Long(String.valueOf(temp.get("pid"))));
            image.setPicPage(new Integer(String.valueOf(temp.get("p"))));
            image.setUserId(new Long(String.valueOf(temp.get("uid"))));
            if (imageService.list(new QueryWrapper<Image>(image)).size() == 0) {
                image.setPicTitle(String.valueOf(temp.get("title")));
                image.setUserName(String.valueOf(temp.get("author")));
                image.setPicR18(Boolean.valueOf(String.valueOf(temp.get("r18"))) ? 1 : 0);
                image.setPicUrl(String.valueOf(temp.get("url")));
                image.setPicMas(String.valueOf(temp.get("url")).replace("original", "master").replace(".jpg", "_master1200.jpg").replace(".png", "_master1200.jpg"));
                image.setPicWidth(new Long(String.valueOf(temp.get("width"))));
                image.setPicHeight(new Long(String.valueOf(temp.get("height"))));
                image.setPicTags(temp.get("tags").toString());
                imageService.save(image);
                countLoad++;
                if (image.getPicR18() == 0)
                    countPart++;
            }
        }
        String result = "Get " + countAll + ", New " + countLoad + ", Load " + countPart + ".";
        System.out.println("======>>>>>>\n= " + webResult + "\n= " + result + "\n======>>>>>>");
        return result;
    }

    private String getImgOn(String keyword) {
        Image image = imageService.getImageByKey(keyword.replace(" ", "%"));
        if (image != null) {
            if (image.getPicStatus() != 1) {
                try {
                    DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicMas());
                    image.setPicStatus(1);
                    image.setPicPath("/profile" + image.getPicMas().substring(image.getPicMas().lastIndexOf("/")));
                    imageService.updateById(image);
                } catch (Exception e1) {
                    try {
                        DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicUrl());
                        image.setPicStatus(1);
                        image.setPicPath("/profile" + image.getPicUrl().substring(image.getPicUrl().lastIndexOf("/")));
                        imageService.updateById(image);
                    } catch (Exception e2) {
                        image.setPicStatus(2);
                        image.setPicPath("");
                        imageService.updateById(image);
                    }
                }
            }
            String result = "Found " + imageService.getImageSizeByKey(keyword.replace(" ", "%")) + ".\n" + getImgResult(image);
            return result;
        } else {
            String result = "Found 0.";
            return result;
        }
    }

    private String getImgOff(String keyword) {
        keyword = keyword.replace(" ", "%");
        Image image = keyword.startsWith("!") ? imageService.getImageByKeyNot(keyword.substring(1)) : imageService.getImageByKey(keyword);

        if (image != null) {
            if (image.getPicStatus() != 1) {
                try {
                    DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicMas());
                    image.setPicStatus(1);
                    image.setPicPath("/profile" + image.getPicMas().substring(image.getPicMas().lastIndexOf("/")));
                    imageService.updateById(image);
                } catch (Exception e1) {
                    try {
                        DownloadUtil.download(RuoYiConfig.getProfile(), image.getPicUrl());
                        image.setPicStatus(1);
                        image.setPicPath("/profile" + image.getPicUrl().substring(image.getPicUrl().lastIndexOf("/")));
                        imageService.updateById(image);
                    } catch (Exception e2) {
                        image.setPicStatus(2);
                        image.setPicPath("");
                        imageService.updateById(image);
                    }
                }
            }
            String result = "Found " + (keyword.startsWith("!") ? imageService.getImageSizeByKeyNot(keyword.substring(1)) : imageService.getImageSizeByKey(keyword)) + ".\n" + getImgResult(image);
            return result;
        } else {
            String result = "Found 0.";
            return result;
        }
    }

    private String getImgResult(Image image) {
        return "Pid:" + image.getPicId() + " - Uid:" + image.getUserId() + "\nTitle:" + image.getPicTitle() + "\nAuthor:" + image.getUserName() + "\n[CQ:image,url=http://localhost:8080" + image.getPicPath() + "]";
    }

    public Recommend getRecommend() {
        return recommendService.getCurrentRecommend();
    }
    private String getTarget(Long userId) {
        return "[CQ:at,qq=" + userId + "]";
    }
    /*
    private Long getTarget(String content) {
        Pattern p = Pattern.compile("\\[CQ:at,qq=\\d*\\]");
        Matcher m = p.matcher(content);
        String target = "";
        if (m.find())
            target = m.group(0).replace("[CQ:at,qq=", "").replace("]", "");
        else
            return 0l;
        return Long.valueOf(target);
    }
    private MsgLog sendPrivateMsg(CoolQ cq, Long userId, String msg) {
        MsgLog msgLog = new MsgLog();
        msgLog.setMsgId(new Long(((MessageData) cq.sendPrivateMsg(userId, msg, false).getData()).getMessageId()));
        msgLog.setMsgContent(msg);
        msgLog.setUserId(userId);
        msgLog.setMsgType("resp");
        msgLogService.save(msgLog);
        System.out.println("[System] -> [" + userId + "] : " + msg);
        return msgLog;
    }
    */

    private MsgLog sendGroupMsg(CoolQ cq, Long groupId, String msg) {
        MsgLog msgLog = new MsgLog();
        msgLog.setMsgId(new Long(((MessageData) cq.sendGroupMsg(groupId, msg, false).getData()).getMessageId()));
        msgLog.setMsgContent(msg);
        msgLog.setGroupId(groupId);
        msgLog.setMsgType("resp");
        msgLogService.save(msgLog);
        System.out.println("[System] => [" + groupId + "] : " + msg);
        return msgLog;
    }

    private void sendGroupMsg(CoolQ cq, Long groupId, String msg, boolean del) {
        MsgLog msgLog = sendGroupMsg(cq, groupId, msg);
        if (del)
            delGroupMsg(cq, msgLog.getMsgId());
    }

    private void delGroupMsg(CoolQ cq, Long msgId) {
        Integer time = Integer.valueOf(optionService.getOption("DelMsgDelay").getOptionValue());
        new Executor(cq, msgId.intValue(), time) {
            @Override
            public void run() {
                try {
                    sleep(getTime() * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                getCq().deleteMsg(getMsgId());
            }
        }.start();
    }


    private boolean checkSender(Conver conver, Long senderId) {
        return conver.getUserId() == 0 || conver.getUserId().equals(senderId);
    }

    private boolean checkGroup(Conver conver, Long groupId) {
        return conver.getGroupId() == 0 || conver.getGroupId().equals(groupId);
    }

    private boolean check(Conver conver, Long groupId, Long senderId) {
        return checkGroup(conver, groupId) && checkSender(conver, senderId);
    }

    private boolean checkFUNC(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && ((Map) JSON.parse(conver.getConverResp())).get("type").equals("FUNC");
    }

    private boolean checkANSWERS(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && ((Map) JSON.parse(conver.getConverResp())).get("type").equals("ANSWERS");
    }

    private boolean checkTEXTS(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && ((Map) JSON.parse(conver.getConverResp())).get("type").equals("TEXTS");
    }

    private boolean checkMAIL(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && ((Map) JSON.parse(conver.getConverResp())).get("type").equals("MAIL");
    }

    private boolean checkAPI(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && ((Map) JSON.parse(conver.getConverResp())).get("type").equals("API");
    }

    private boolean checkONLINE(Conver conver, Long groupId, Long senderId) {
        return ((Map) JSON.parse(conver.getConverResp())).get("status").equals("ONLINE");
    }

    private boolean checkOFFLINE(Conver conver, Long groupId, Long senderId) {
        return ((Map) JSON.parse(conver.getConverResp())).get("status").equals("OFFLINE");
    }

    private boolean checkSETU(Conver conver, Long groupId, Long senderId) {
        return check(conver, groupId, senderId) && (((Map) JSON.parse(conver.getConverResp())).get("type").equals("SETU"));
    }

    private boolean inCD(String key, Object suffix) {
        return redisUtils.hasKey(key + suffix.toString());
    }

    private void setCD(String key, Object suffix) {
        redisUtils.set(key + suffix.toString(), 0, Integer.valueOf(optionService.getOption(key).getOptionValue()));
    }

    private long getCD(String key, Object suffix) {
        return redisUtils.getExpire(key + suffix.toString());
    }

    private void delCD(String key, Object suffix) {
        redisUtils.del(key + suffix);
    }

    private boolean isAdmin(Long senderId) {
        return senderId.equals(Long.valueOf(optionService.getOption("Admin").getOptionValue()));
    }

    private boolean head(String req, String key) {
        return req.startsWith(key);
    }

    private String cmd(String req) {
        return req.contains(" ") ? req.substring(0, req.indexOf(" ")) : req;
    }

    private String param(String req) {
        return req.contains(" ") ? req.substring(req.indexOf(" ") + 1) : "";
    }
}
